"""1D variable reconstruction algorithms"""

import muscl_limiters

import numpy

class ReconstructionFunction:
    """Base class for all reconstructions"""

    def __init__(self, grid):
        self.grid = grid
        self._setup()

    def reconstruct(self):
        """Perform the reconstruction"""
        raise NotImplementedError("Reconstruct::reconstruct called")

    def _setup(self):
        """Setup reconstruction parameters"""
        raise NotImplementedError("Reconstruct::_setup called")

class MUSCL(ReconstructionFunction):
    """MUSCL type second order reconstruction.

    For each conserved variable, a slope parameter is defined based on
    neighbor cell values. In general, this approach results in a five
    point stencil.

    Boundary extrapolated values are then obtained using the slope
    parameter to define interfae values which are used to obtain the
    intercell numerical flux.

    """
    def __init__(self, grid, limiter_type=0):
        ReconstructionFunction.__init__(self, grid)

        # set the limiter function
        self.limiter = muscl_limiters.FirstOrder()
        
    def reconstruct(self):
        """Set the slopes for the variables.

        Specifically, the conserved variables for the grid are
        compared and a slope value is assigned to each cell.
                
        """
        grid = self.grid
        nb = grid.nb

        # generate the slopes
        for cell in grid.cells[nb:-nb]:
            pass

    def get_conserved_variables(self, face, index):
        """Get the boundary extrapolated values at the cell interfaces."""
        grid = self.grid

        # get the cell to the left and right of this face
        left, right = face.left, face.right

        # get the cell lengths
        dxl, dxr = left.dx, right.dx

        # generate the boundary extrapolated values
        ql = left.q + left.slope * 0.5 * dxl
        qr = right.q - right.slope * 0.5 * dxr

        return ql, qr        
    
    def _setup(self):
        """Setup the MUSCL related parameters for the grid.
        
        In particular, a slope variable is defined in each cell for
        each conserved variable. This slope may then be used to
        generate the boundary extrapolated values.

        Since the MUSCL reconstruction results in a five point
        stencil, we expect two ghost cells. Slope values not set for
        these ghost cells.
        
        """
        grid = self.grid
        if grid.nb < 2:
            msg = "MUSCL reconstruction requires at least two ghost cells!"
            raise RuntimeError(msg)
        
        for cell in grid.cells:
            cell.slopes = numpy.zeros( grid.nvar )
        
    
class ReconstructionType:
    MUSCL = 0
    PPM = 1
    ENO = 2

reconstruction_methods = [

    ("MUSCL", MUSCL) ]
